/*
 * Copyright (c) 2003-2008 jMonkeyEngine
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 
 *   may be used to endorse or promote products derived from this software 
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * Copied from jme 2.0 and modified for FireworkMasher
 */
package fwm;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;

import org.jfugue.Pattern;
import org.jfugue.StreamingPlayer;

import com.jme.scene.Node;

import com.jme.bounding.BoundingBox;
import com.jme.image.Texture;
import com.jme.math.FastMath;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.Controller;
import com.jme.scene.state.BlendState;
import com.jme.scene.state.TextureState;
import com.jme.scene.state.ZBufferState;
import com.jme.scene.state.BlendState.DestinationFunction;
import com.jme.scene.state.BlendState.SourceFunction;
import com.jme.scene.state.BlendState.TestFunction;
import com.jme.system.DisplaySystem;
import com.jme.util.TextureManager;
import com.jmex.effects.particles.ParticleFactory;
import com.jmex.effects.particles.ParticleMesh;

public class ExplosionFactory {
    
    private static ArrayList<ParticleMesh> explosions = new ArrayList<ParticleMesh>();
    private static HashMap<Integer, ColorPair> colors = new HashMap<Integer, ColorPair>();
    private static HashMap<Integer, String> patterns = new HashMap<Integer, String>();
    private static BlendState bs;
    private static TextureState ts;
    private static ZBufferState zstate;
	private static StreamingPlayer player = new StreamingPlayer();
	private static Random r = new Random();
	private static Node rootNode;

    public static void cleanExplosions() {
        int count = 0;
        for (int x = 0, tSize = explosions.size(); x < tSize; x++) {
            ParticleMesh e = (ParticleMesh)explosions.get(x);
            if (!e.isActive()) {
                if (e.getParent() != null)
                    e.removeFromParent();
                count++;
                if (count > 5) {
                    explosions.remove(x);
                    tSize--;
                }
            }
        }
    }

    public static ParticleMesh getExplosion(int keyIndex) {
        for (int x = 0, tSize = explosions.size(); x < tSize; x++) {
            ParticleMesh e = (ParticleMesh)explosions.get(x);
            if (!e.isActive()) {
            	setColors(e, keyIndex);
                return e;
            }
        }
        ParticleMesh e = createExplosion();
    	setColors(e, keyIndex);
        return e;
    }
    
    private static void setColors(ParticleMesh e, int keyIndex) {
    	ColorPair cp = getKeyColor(keyIndex);
    	e.setStartColor(cp.startColor);
		e.setEndColor(cp.endColor);
    }
    
    private static ColorPair getKeyColor(int keyIndex) {
    	ColorPair cp = colors.get(keyIndex);
    	if (cp == null) {
//    		cp = new ColorPair(new ColorRGBA(1.0f, 0.312f, 0.121f, 1.0f),
//    				           new ColorRGBA(1.0f, 0.24313726f, 0.03137255f, 0.0f) );
    		cp = new ColorPair(new ColorRGBA((float) Math.random(), (float) Math.random(),
    				                         (float) Math.random(), 1.0f),
	                           new ColorRGBA((float) Math.random(), (float) Math.random(),
				                             (float) Math.random(), 0.0f) );    		
    		colors.put(keyIndex, cp);
    	}
    	
    	return cp;
    }
    
    private static ParticleMesh createExplosion() {
        ParticleMesh explosion = ParticleFactory.buildParticles("explosion", 100);        
		explosion.setEmissionDirection( new Vector3f( 0.0f, 1.0f, 0.0f ) );
		explosion.getParticleController().setSpeed(0.3f);
		explosion.setMaximumAngle(FastMath.PI);
		explosion.setMinimumAngle(0);
		explosion.setMinimumLifeTime(100.0f);
		explosion.setMaximumLifeTime(350.0f);
        explosion.setStartSize( 2.0f );
		explosion.setEndSize( 2.0f );
		explosion.setInitialVelocity( 0.3f );
		explosion.getParticleController().setControlFlow(false);
		explosion.getParticleController().setRepeatType(Controller.RT_CLAMP);
				
		explosion.setModelBound(new BoundingBox());
		explosion.updateModelBound();

        explosion.setRenderState(ts);
        explosion.setRenderState(bs);
        explosion.setRenderState(zstate);
        explosion.updateRenderState();
        
        explosions.add(explosion);
        
        //rootNode appears NULL at this point
        rootNode.attachChild( explosion );
        
        return explosion;
    }

    public static void warmup(Node rootNode) {
        DisplaySystem display = DisplaySystem.getDisplaySystem();
        bs = display.getRenderer().createBlendState();
        bs.setBlendEnabled(true);
        bs.setSourceFunction(SourceFunction.SourceAlpha);
        bs.setDestinationFunction(DestinationFunction.One);
        bs.setTestEnabled(true);
        bs.setTestFunction(TestFunction.GreaterThan);

        ts = display.getRenderer().createTextureState();
        ts.setTexture(TextureManager.loadTexture(
                ExplosionFactory.class.getClassLoader().getResource(
                        "media/flaresmall.jpg"), 
						Texture.MinificationFilter.Trilinear,
						Texture.MagnificationFilter.Bilinear));

        zstate = display.getRenderer().createZBufferState();
        zstate.setEnabled(false);

        ExplosionFactory.rootNode = rootNode;
        ParticleMesh e = null;
        for (int i = 0; i < 40; i++) {
        	e = createExplosion();
        	e.forceRespawn();
        }
    }
    
    public static void playSound(int keyCode) {
		//play a sound
		player.stream(getKeyPattern(keyCode));
		//System.out.println("*** key=" + keyCode);
    }
    
    private static String getKeyPattern(int keyIndex) {
    	String p = patterns.get(keyIndex);
    	if (p == null) {
    		//p = "[" + r.nextInt(128) +"]";
    		p = "[" + keyIndex%128 +"]";
    		patterns.put(keyIndex, p);
    	}    	
    	return p;
    }    

}

class ColorPair {
	ColorRGBA startColor;
	ColorRGBA endColor;
	public ColorPair(ColorRGBA c1, ColorRGBA c2) {
		startColor = c1;
		endColor = c2;
	}
}